home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / sbin / ndiswrapper < prev    next >
Text File  |  2006-05-11  |  23KB  |  1,015 lines

  1. #!/usr/bin/perl
  2.  
  3. #/*
  4. #*  Copyright (C) 2005 Pontus Fuchs, Giridhar Pemmasani
  5. #*
  6. #*
  7. #*  This program is free software; you can redistribute it and/or modify
  8. #*  it under the terms of the GNU General Public License as published by
  9. #*  the Free Software Foundation; either version 2 of the License, or
  10. #*  (at your option) any later version.
  11. #*
  12. #*  This program is distributed in the hope that it will be useful,
  13. #*  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. #*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. #*  GNU General Public License for more details.
  16. #*
  17. #*/
  18.  
  19.  
  20. #use strict;
  21. use Fcntl ':mode';
  22. use File::Basename;
  23. use File::Copy;
  24. use File::Path;
  25.  
  26. my $WRAP_PCI_BUS = 5;
  27. my $WRAP_PCMCIA_BUS = 8;
  28. my $WRAP_USB_BUS = 15;
  29.  
  30. my @sections;
  31. my %strings;
  32. my %version;
  33. my $driver_name;
  34. my $confdir = "/etc/ndiswrapper";
  35. my $instdir;
  36. my %fuzzlist;
  37. my %buslist;
  38. # bustype is either PCI or USB, whereas BusType used in INF file can
  39. # be different
  40. my $bus;
  41. my $classguid;
  42.  
  43. #Blacklist of files not to install.
  44. my @copy_blacklist;
  45.  
  46. #Fixup list for parameters. 
  47. my %param_fixlist = ("EnableRadio|0" => "EnableRadio|1",
  48.              "IBSSGMode|0" => "IBSSGMode|2",
  49.                      "PrivacyMode|0" => "PrivacyMode|2",
  50.              "AdhocGMode|1" => "AdhocGMode|0");
  51.  
  52. if(@ARGV < 1) {
  53.     usage();
  54.     exit();
  55. }
  56.  
  57. my $modconf;
  58. if (`uname -r` =~ /(\d+)\.(\d+)\.(\d+)/) {
  59.     if ($2 > 4) {
  60.     if (-d "/etc/modprobe.d") {
  61.         $modconf = "/etc/modprobe.d/ndiswrapper" 
  62.     } else {
  63.         $modconf = "/etc/modprobe.conf" 
  64.     }
  65.     } else {
  66.     if (-d "/etc/modutils") {
  67.         $modconf = "/etc/modutils/ndiswrapper";
  68.     } else {
  69.         $modconf = "/etc/modules.conf";
  70.     }
  71.     }
  72. }
  73.  
  74. my $res;
  75. if($ARGV[0] eq "-i" and @ARGV == 2) {
  76.     $res = install($ARGV[1]);
  77. } elsif($ARGV[0] eq "-d" and @ARGV == 3) {
  78.     $res = devid_driver($ARGV[1], $ARGV[2]);
  79. } elsif($ARGV[0] eq "-e" and @ARGV == 2) {
  80.     $res = remove($ARGV[1]);
  81. } elsif($ARGV[0] eq "-l" and @ARGV == 1) {
  82.     $res = list();
  83. } elsif($ARGV[0] eq "-m" and @ARGV == 1) {
  84.     $res = modalias();
  85. } elsif($ARGV[0] eq "-v" and @ARGV == 1) {
  86.     printf "utils "; system("/sbin/loadndisdriver -v");
  87.     printf "driver ";
  88.     system("modinfo ndiswrapper | grep -E '^version|^vermagic'");
  89.     $res = 0;
  90. } elsif($ARGV[0] eq "-da" and @ARGV == 1) {
  91.     $res = genmoddevconf(0);
  92. } elsif($ARGV[0] eq "-di" and @ARGV == 1) {
  93.     $res = genmoddevconf(1);
  94. } else {
  95.     usage();
  96.     exit();
  97. }
  98.  
  99. exit $res;
  100.  
  101. sub usage {
  102.     print "Usage: ndiswrapper OPTION\n\n" .
  103.       "Manage ndis drivers for ndiswrapper.\n"  .
  104.     "-i inffile        Install driver described by 'inffile'\n" .
  105.     "-d devid driver   Use installed 'driver' for 'devid'\n" .
  106.     "-e driver         Remove 'driver'\n" .
  107.     "-l                List installed drivers\n" .
  108.     "-m                Write configuration for modprobe\n" .
  109.     "-da               Write module alias configuration for all devices\n" .
  110.     "-di               Write module install configuration for all devices\n" .
  111.     "-v                Report version information\n" .
  112.     "\n\nwhere 'devid' is either PCIID or USBID of the form XXXX:XXXX\n";
  113. }
  114.  
  115. sub install {
  116.     my $inf = shift;
  117.     $driver_name = lc($inf);
  118.     $driver_name =~ s/\.inf//;
  119.     $driver_name = basename($driver_name);
  120.     $instdir = dirname($inf);
  121.     chomp($instdir);
  122.     chomp($driver_name);
  123.  
  124.     if (isInstalled($driver_name)) {
  125.     print "$driver_name is already installed. Use -e to remove it\n";
  126.     return -1;
  127.     }
  128.     if (opendir(DH, $confdir)) {
  129.     closedir(DH);
  130.     } else {
  131.     mkdir($confdir);
  132.     }
  133.  
  134.     print "Installing $driver_name\n";
  135.     if (!mkdir("$confdir/$driver_name")) {
  136.     print "Unable to create directory $confdir/$driver_name." .
  137.       "Make sure you are running as root\n";
  138.     return -1;
  139.     }
  140.  
  141.     loadinf($inf);
  142.     initStrings();
  143.     parseVersion();
  144.     copy("$inf", "$confdir/$driver_name/$driver_name.inf") or
  145.       die "couldn't copy $inf";
  146.     processPCIFuzz();
  147. }
  148.  
  149. sub isInstalled {
  150.     my $installed;
  151.     my $name = shift;
  152.     my $stat = (stat("$confdir"))[2];
  153.     if (!S_ISDIR($stat)) {
  154.     return 0;
  155.     }
  156.     open(LS, "ls -1 $confdir|");
  157.     while(my $f = <LS>) {
  158.     chomp($f);
  159.     $stat = (stat("$confdir/$f"))[2];
  160.     if (S_ISDIR($stat) and $name eq $f) {
  161.         $installed = 1;
  162.     }
  163.     }
  164.     close(LS);    
  165.     return $installed;
  166. }
  167.  
  168. sub remove {
  169.     my $name = shift;
  170.     if (!isInstalled($name)) {
  171.     print "Driver $name is not installed." . 
  172.       "Use -l to list installed drivers\n";
  173.     return;
  174.     }
  175.     rmtree("$confdir/$name", 0, 1);
  176. }
  177.  
  178. sub devid_driver {
  179.     my $devid = shift;
  180.     my $driver = shift;
  181.     my $done = 0;
  182.  
  183.     $devid = uc($devid);
  184.     if (!($devid =~ /[0-9A-Z]{4}:[0-9A-Z]{4}/)) {
  185.     print "'$devid' is not a valid device ID\n";
  186.     return;
  187.     }
  188.     open(LS, "ls -1 $confdir/$driver/ |");
  189.     while (my $f = <LS>) {
  190.     chomp($f);
  191.     if ($f =~ /\.([0-9A-F]+).conf$/) {
  192.         symlink("$f", "$confdir/$driver/$devid.$1.conf");
  193.         print "Driver '$driver' is used for '$devid'\n";
  194.         $done = 1;
  195.         last;
  196.     }
  197.     }
  198.     close(LS);    
  199.     if ($done == 0) {
  200.     print "Driver '$driver' is not installed properly!\n";
  201.     }
  202.     return;
  203. }
  204.  
  205. sub genmoddevconf {
  206.     my $mode = shift;
  207.     my $vendor, $device, $subvendor, $subdevice, $bustype, $busid;
  208.     my $line;
  209.  
  210.     my $moddevconf;
  211.     if (-d "/etc/modprobe.d") {
  212.     $moddevconf = "/etc/modprobe.d/ndiswrapper";
  213.     } elsif (-d "/etc/modules.d") {
  214.     $moddevconf = "/etc/modules.d/ndiswrapper";
  215.     } else {
  216.     $moddevconf = "/etc/ndiswrapper/ndiswrapper";
  217.     }
  218.  
  219.     if (!open(CONF, "| sort >$moddevconf")) {
  220.     print "Unable to create modules alias file $moddevconf\n";
  221.     return -1;
  222.     }
  223.     open(LS, "ls -1 $confdir|");
  224.     while (my $driver = <LS>) {
  225.     chomp($driver);
  226.     my $stat = (stat("$confdir/$driver"))[2];
  227.     if (S_ISDIR($stat)) {
  228.         open(LS2, "ls -1 $confdir/$driver/ |");
  229.         while (my $file = <LS2>) {
  230.         chomp ($file);
  231.         my $line = $file;
  232.         if ($file =~ s/.conf//) {
  233.             if ($file =~ /(.{4}):(.{4}):(.{4}):(.{4})\.([05F])/) {
  234.             $vendor = $1;
  235.             $device = $2;
  236.             $subvendor = "0000$3";
  237.             $subdevice = "0000$4";
  238.             $busid = "$5";
  239.             } elsif($file =~ /(.{4}):(.{4})\.([05F])/) {
  240.             $vendor = $1;
  241.             $device = $2;
  242.             $subvendor = "*";
  243.             $subdevice = "*";
  244.             $busid = "$3";
  245.             }
  246.             my $devstring;
  247.             if ($busid eq "0" or $busid eq "F") {
  248.             $devstring = sprintf("usb:v%sp%sd*dc*dsc*dp*ic*isc*ip*",
  249.                          $vendor, $device);
  250.             } elsif ($busid eq "5") {
  251.             $devstring = sprintf("pci:v0000%sd0000%ssv%ssd%sbc*sc*i*",
  252.                          $vendor, $device, $subvendor,
  253.                          $subdevice);
  254.             } else {
  255.             print stderr "wrong bustype ($busid) for " .
  256.               "configuration file $line - ignoring it\n";
  257.             next;
  258.             }
  259.             if ($mode == 0) {
  260.             printf CONF "alias %s ndiswrapper\n", $devstring;
  261.             } else {
  262.             printf CONF "install %s /sbin/modprobe ndiswrapper\n",
  263.               $devstring;
  264.             }
  265.         }
  266.         }
  267.         close(LS2);
  268.     }
  269.     }
  270.  
  271.     close(CONF);
  272.     close(LS);
  273.  
  274.     print "Module configuration information is stored in $moddevconf\n";
  275.     return 0;
  276. }
  277.  
  278. sub list {
  279.     my $s;
  280.     my $cards = getPresentCards();
  281.  
  282.     if (!$cards) {
  283.     print "WARNING: Cannot locate lspci and lsusb." .
  284.       "Unable to see if hardware is present.\n";
  285.     }
  286.  
  287.     my $stat = (stat("$confdir"))[2];
  288.     if (!S_ISDIR($stat)) {
  289.     print "No drivers installed\n$s";
  290.     return;
  291.     }
  292.     open(LS, "ls -1 $confdir|");
  293.     while (my $f = <LS>) {
  294.     chomp($f);
  295.     my $stat = (stat("$confdir/$f"))[2];
  296.     if (S_ISDIR($stat)) {
  297.         $s .= "$f\t".installStatus($cards, $f)."\n";
  298.     }
  299.     }
  300.     if ($s) {
  301.     print "Installed drivers:\n$s";
  302.     } else {
  303.     print "No drivers installed\n$s";
  304.     }
  305.     close(LS);    
  306. }
  307.  
  308. sub modalias {
  309.     my $alias = 0;
  310.  
  311.     open(MODPROBE, "modprobe -c|");
  312.     while (my $line = <MODPROBE>) {
  313.     if ($line =~ /^alias\s.+\sndiswrapper/) {
  314.         print "modprobe config already contains alias directive\n\n";
  315.         $alias = 1;
  316.     } elsif ($line =~ /^install\s.*ndiswrapper/) {
  317.         printf stderr "module configuration contains directive $line;" .
  318.           "you should delete that";
  319.     } elsif ($line =~ /^post-install\s+ndiswrapper/) {
  320.         printf stderr "module configuration contains directive $line;" .
  321.           "you should delete that";
  322.     }
  323.     }
  324.     close(MODPROBE);
  325.  
  326.     if ($alias) {
  327.     return;
  328.     }
  329.  
  330.     print "Adding \"alias wlan0 ndiswrapper\" to $modconf\n";
  331.     system("echo \"alias wlan0 ndiswrapper\" >>$modconf");
  332.     if (-x "/sbin/update-modules") {
  333.     system("/sbin/update-modules");
  334.     }
  335. }
  336.  
  337. sub getPresentCards {
  338. #01:00.0 Class 0300: 1002:4c66 (rev 01)
  339. #        Subsystem: 1043:1732
  340.     my @cards;
  341.     my @lspci = ("/sbin/lspci", "/usr/sbin/lspci", "lspci");
  342.     for (my $i = 0; $i < @lspci; $i++) {
  343.     if (open(LSPCI, "$lspci[$i] -vn|")) {
  344.         my $card;
  345.         while(my $line = <LSPCI>) {
  346.         if($line =~ /^[0-9]+.*:\s(.{4}):(.{4}).*/) {
  347.             my %c;
  348.             $card = \%c;
  349.             $card->{vendor} = $1;
  350.             $card->{device} = $2;
  351.         }
  352.         if ($line =~ /.+Subsystem:\s*(.{4}):(.{4}).*/) {
  353.             $card->{subvendor} = $1;
  354.             $card->{subdevice} = $2;
  355.             push(@cards, $card);
  356.         }
  357.         }
  358.         last;
  359.     }
  360.     }
  361.  
  362.     my @lsusb = ("/sbin/lsusb", "/usr/sbin/lsusb", "lsusb");
  363.     for(my $i = 0; $i < @lsusb; $i++) {
  364.     if (open(LSUSB, "$lsusb[$i] |")) {
  365.         my $card;
  366.         while(my $line = <LSUSB>) {
  367.         if($line =~ /.*: ID\s(.{4}):(.{4}).*/) {
  368.             my %c;
  369.             $card = \%c;
  370.             $card->{vendor} = $1;
  371.             $card->{device} = $2;
  372.  
  373.             push(@cards, $card);
  374.         }
  375.         }
  376.         last;
  377.     }
  378.     }
  379.     return \@cards;
  380. }
  381.  
  382. sub installStatus {
  383.     my $cards = shift; 
  384.     my $driver = shift;    
  385.  
  386.     my $sys = 0;
  387.     my $conf = 0;
  388.     my $inf = 0;
  389.  
  390.     if (!$cards) {
  391.     return;
  392.     }
  393.  
  394.     open(LS2, "ls -1 $confdir/$driver|");
  395.  
  396.     while (my $device = <LS2>)     {
  397.     chomp($device);
  398.     my $d = $device;
  399.  
  400.     $sys = 1 if $d =~ /\.sys$/;
  401.     $inf = 1 if $d =~ /\.inf$/;
  402.     $conf = 1 if $conf eq 0 and $d =~ /\.conf$/;
  403.     $d =~ s/.conf//;
  404.     if ($d =~ /(.{4}):(.{4}):(.{4}):(.{4})/) {
  405.         for (my $i = 0; $$cards[$i]; $i++) {
  406.         if ($$cards[$i]->{vendor} == $1 and
  407.             $$cards[$i]->{device} == $2 and
  408.             $$cards[$i]->{subvendor} == $3 and
  409.             $$cards[$i]->{subdevice} == $4) {
  410.             $conf = 3;
  411.             last;
  412.         }
  413.         }
  414.     } elsif($d =~ /(.{4}):(.{4})/) {
  415.         for (my $i = 0; $$cards[$i]; $i++) {
  416.         if ($$cards[$i]->{vendor} == $1 and
  417.             $$cards[$i]->{device} == $2) {
  418.             my $stat = (lstat("$confdir/$driver/$device"))[2];
  419.             if (S_ISLNK($stat)) {
  420.             $conf = 2;
  421.             } else {
  422.             $conf = 3;
  423.             }
  424.             last;
  425.         }
  426.         }
  427.     }
  428.     }
  429.     close(LS2);    
  430.  
  431.     my $ret;
  432.     if ($sys eq 0 || $inf eq 0 || $conf eq 0) {
  433.     $ret = "invalid driver!";
  434.     } else {
  435.     $ret = "\tdriver installed " if $conf eq 1;
  436.     $ret = "\tdriver installed, hardware present " if $conf eq 2;
  437.     $ret = "\tdriver installed, hardware present " if $conf eq 3;
  438.     }
  439.     return $ret;
  440. }
  441.  
  442. #
  443. # Create symlink for PCI general device if not existing
  444. #
  445. sub processPCIFuzz {
  446.     my @devs = keys(%fuzzlist);
  447.     for (my $i = 0; $i < @devs; $i++) {
  448.     my $dev = $devs[$i];
  449.     if ($dev ne $fuzzlist{$dev}) {
  450.         my $bt = $buslist{$dev};
  451.         my $src = "$confdir/$driver_name/$fuzzlist{$dev}.$bt.conf";
  452.         my $dst = "$confdir/$driver_name/$dev.$bt.conf";
  453.         symlink("$src", "$dst");
  454.     }
  455.     }
  456. }
  457.  
  458. #
  459. # Collect a list of supported PCI-Id's so we can add fuzzy entries if needed.
  460. #
  461. sub addPCIFuzzEntry {
  462.     my $vendor = shift;
  463.     my $device = shift;
  464.     my $subvendor = shift;
  465.     my $subdevice = shift;
  466.     my $bus = shift;
  467.  
  468.     my $s = "$vendor:$device";
  469.  
  470.     if (!$subvendor or !$fuzzlist{$s}) {
  471.     my $s2 = $s;
  472.     if ($subvendor) {
  473.         $s2 .= ":$subvendor:$subdevice";
  474.     }
  475.     $fuzzlist{$s} = $s2;
  476.     $buslist{$s} = $bus;
  477.     }
  478. }
  479.  
  480. sub parseVersion {
  481.     my $s = getSection("version");
  482.     if (!$s) {
  483.     return;
  484.     }
  485.     my @lines = split("\n", $s->{data});
  486.  
  487.     for (my $i = 0; $i < @lines; $i++) {
  488.     (my $key, my $val) = getKeyVal($lines[$i]);
  489.     if ($key eq "Provider") {
  490.         $val =~ s/"(.+)"/$1/; 
  491.         $version{$key} = $val;
  492.     }
  493.     if ($key eq "DriverVer") {
  494.         $val =~ s/"(.+)"/$1/; 
  495.         $version{$key} = $val;
  496.     }
  497.     if ($key eq "ClassGUID") {
  498.         $val =~ s/\{(.+)\}/$1/; 
  499.         $classguid = lc($val);
  500.     }
  501.     }
  502.     parseMfr();
  503. }
  504.  
  505. #
  506. # Parse the [Manufacturer] section.
  507. #
  508. sub parseMfr {
  509.     #Examples:
  510.     #Vendor
  511.     #Vendor,ME,NT,NT.5.1
  512.     #Vendor.NTx86
  513.  
  514.     my $manu = getSection("manufacturer");
  515.     if (!$manu) {
  516.     return -1;
  517.     }
  518.  
  519.     my @lines = split("\n", $manu->{data});
  520.     for (my $i = 0; $i < @lines; $i++) {
  521.     my $line = remComment($lines[$i]);
  522.     (my $key, my $val) = getKeyVal($line, "=");
  523.  
  524.     if ($key eq $version{"Provider"}) {
  525.         $strings{$key} = trim($val);
  526.     }
  527.  
  528.     if ($val) {
  529.         my $section;
  530.         my @flavours = map { stripquotes(trim($_)) } split(",", $val);
  531.         my $flavour = "";
  532.         if(@flavours == 1) {
  533.         #Vendor
  534.         $section = $flavours[0];                
  535.         } else {
  536.         #Vendor,flavour1, flavour2 etc;
  537.         for (my $i = 1; $i < @flavours; $i++) {
  538.             my $flav = $flavours[$i];
  539.             $flav =~ s/\s*(\S+)\s*/$1/;
  540.             if (uc($flav) eq "NT.5.1") {
  541.             #This is the best (XP)
  542.             $section = $flavours[0] . "." . $flav;
  543.             $flavour = $flav;
  544.             } elsif (substr(uc($flav),0,2) eq "NT" and
  545.                  $section eq "") {
  546.             #This is the second best (win2k)
  547.             $section = $flavours[0] . "." . $flav;
  548.             $flavour = $flav;
  549.             }
  550.         }
  551.         }
  552.         my $res = parseVendor($flavour, $section);
  553.         if ($res) {
  554.         return $res;
  555.         }
  556.     }
  557.     }
  558. }
  559.  
  560. #
  561. # Parse a vendor section. This section contains the device-ids.
  562. # Each poiting to a section with config info.
  563. #    
  564. sub parseVendor {
  565.     my $flavour = shift;
  566.     my $vendor_name = shift;
  567.     my $vend = getSection($vendor_name);
  568.  
  569.     if (!$vend) {
  570.     print "no vendor\n";
  571.     return -1;
  572.     }
  573.  
  574.     my @lines = split("\n", $vend->{data});
  575.     for (my $i = 0; $i < @lines; $i++) {
  576.     my $line = remComment($lines[$i]);
  577.     (my $name, my $val) = getKeyVal($line, "=");
  578.  
  579.     if ($val) {
  580.         my $section;
  581.         my $id;
  582.         ($section, $id) = split(",", $val);
  583.         $section = trim($section);
  584.         $id = substStr(trim($id));
  585.         my $bt, $vendor, $device, $subvendor, $subdevice;
  586.         ($bus, $vendor, $device, $subvendor, $subdevice) = parseID($id);
  587.         if ($vendor) {
  588.         parseDevice($flavour, $section, $vendor, $device,
  589.                 $subvendor, $subdevice);
  590.         }
  591.     }
  592.     }
  593. }
  594.  
  595. #
  596. # This section contains pointers to registry sections and copyfiles sections. 
  597. #
  598. sub parseDevice {
  599.     my $flavour = shift;
  600.     my $device_sect = shift;
  601.     my $device = shift;
  602.     my $vendor = shift;
  603.     my $subvendor = shift;
  604.     my $subdevice = shift;
  605.     my $dev;
  606.  
  607.     # for RNDIS INF file (for USR5420), vendor section names device
  608.     # section as RNDIS.NT.5.1, but copyfiles section is RNDIS.NT, so
  609.     # first strip flavour from device_sect and then look for matching
  610.     # section
  611.  
  612.     if ($device_sect eq "RNDIS.NT.5.1") {
  613.     $dev = getSection("RNDIS.NT");
  614.     }
  615.     if (!$dev) {
  616.     $dev = getSection("$device_sect.$flavour");
  617.     }
  618.     if (!$dev) {
  619.     $dev = getSection("$device_sect.NT");
  620.     }
  621.     if (!$dev) {
  622.     $dev = getSection("$device_sect.NTx86");
  623.     }
  624.  
  625.     if (!$dev) {
  626.     $dev = getSection("$device_sect");
  627.     }
  628.     if (!$dev) {
  629.     print "no dev $device_sect $flavour\n";
  630.     return -1;
  631.     }
  632.     # print "$device:$vendor:$subvendor:$subdevice  $flavour\n";
  633.     my @copy_files;
  634.     my $addreg;
  635.     my @lines = split("\n", $dev->{data});
  636.  
  637.     for (my $i = 0; $i < @lines; $i++) {
  638.     my $line = $lines[$i];
  639.     $line =~ s/^;\s*//;
  640.     $line = trim(remComment($line));
  641.     (my $key, my $val) = getKeyVal($line, "=");
  642.     if ($key) {
  643.         if (lc($key) eq "addreg") {
  644.         $addreg = $val;
  645.         } elsif (lc($key) eq "copyfiles") {
  646.         push @copy_files, $val;
  647.         } elsif ($key eq "BusType") {
  648.         $strings{$key} = $val;
  649.         }
  650.     }
  651.     }        
  652.  
  653.     my $filename = "$device:$vendor";
  654.     if ($subvendor) {
  655.     $filename .= ":$subvendor:$subdevice"
  656.     }
  657.  
  658.     my $bt = sprintf("%X", $bus);
  659.     $filename .= ".$bt.conf";
  660.     if ($bus == $WRAP_PCI_BUS || $bus == $WRAP_PCMCIA_BUS) {
  661.     addPCIFuzzEntry($device, $vendor, $subvendor, $subdevice, $bt);
  662.     }
  663.  
  664.     if (!open(CONF, ">$confdir/$driver_name/$filename")) {
  665.     print "Unable to create file $filename";
  666.     return -1;
  667.     }
  668.  
  669.     my $ver=$version{"DriverVer"};
  670.     my $provider=$version{"Provider"};
  671.     my $providerstring = stripquotes(substStr(trim($provider)));
  672.  
  673.     printf CONF "NdisVersion|0x50001\n";
  674.     printf CONF "Environment|1\n";
  675.     if ($strings{"BusType"} ne "") {
  676.     printf CONF "BusType|$strings{\"BusType\"}\n";
  677.     }
  678.     printf CONF "class_guid|$classguid\n";
  679.     printf CONF "mac_address|XX:XX:XX:XX:XX:XX\n";
  680.     printf CONF "driver_version|$providerstring,$ver\n";
  681.     printf CONF "\n";
  682.     close(CONF);
  683.  
  684.     if (!open(CONF, "|sort|uniq >>$confdir/$driver_name/$filename")) {
  685.     print "Unable to create file $filename";
  686.     return -1;
  687.     }
  688.  
  689.     my @addregs = split(",", $addreg);
  690.     for (my $i = 0; $i < @addregs; $i++) {
  691.     my $reg = trim($addregs[$i]);
  692.     addReg($reg);
  693.     }
  694.     for (my $i = 0; $i < @copy_files; $i++) {
  695.     my @copy_sec = split(",", $copy_files[$i]);
  696.     for (my $j = 0; $j < @copy_sec; $j++) {
  697.         my $file = trim($copy_sec[$j]);
  698.         copyfiles($file);
  699.     }
  700.     }
  701.     close(CONF);
  702. }
  703.  
  704. #
  705. # Process a copyfiles section.
  706. #
  707. sub copyfiles {
  708.     my $copy_name = shift;
  709.     my $copy;
  710.  
  711.     if ($copy_name =~ /^\@/) {
  712.     $copy_name =~ s/^\@//;
  713.     return copy_file($copy_name);
  714.     }
  715.  
  716.     $copy = getSection($copy_name);
  717.     if (!$copy) {
  718.     printf "Parse error in inf. Unable to find section $copy_name\n";
  719.     return -1;
  720.     }
  721.  
  722.     my @lines = split("\n", $copy->{data});
  723.  
  724.     for (my $i = 0; $i < @lines; $i++) {
  725.     my $line = $lines[$i];
  726.     $line = trim($line);
  727.  
  728.     last if ($line =~ /^\[/);
  729.     my @files = split(",", $line);
  730.     for (my $j = 0; $j < @files; $j++) {
  731.         my $file = $files[$j];
  732.         $file = trim($file);
  733.         if ($file and length($file) > 0) {
  734.         copy_file($file);
  735.         }
  736.     }
  737.     }
  738.     return 0;
  739. }
  740.  
  741. sub copy_file {
  742.     my $file = shift;
  743.     $file =~ s/^;//;
  744.     $file = trim(remComment($file));
  745.     $file =~ s/,+.*//;
  746.     $file = trim($file);
  747.     my $nocopy = 0;
  748.     for (my $k = 0; $k < @copy_blacklist; $k++) {
  749.     if ($copy_blacklist[$k] eq lc($file)) {
  750.         $nocopy = 1;
  751.     }
  752.     }
  753.     my $dir = finddir($file);
  754.     if ($dir) {
  755.     $dir = findfile("", $dir);
  756.     }
  757.  
  758.     my $realname = findfile($dir, $file);
  759.  
  760.     if ($realname) {
  761.     my $newname = lc($realname);
  762.     if ($dir) {
  763.         $realname = "$dir/$realname";
  764.     }
  765.     if (!$nocopy) {
  766.         copy("$instdir/$realname", "$confdir/$driver_name/$newname");
  767.         chmod(0644, "$confdir/$driver_name/$newname");
  768.     }
  769.     }
  770. }
  771.  
  772. sub finddir {
  773.     my $filename = shift;
  774.     my $sourcedisksfiles = getSection("sourcedisksfiles");
  775.     if (!$sourcedisksfiles) {
  776.     return "";
  777.     }
  778.     my @lines = split("\n", $sourcedisksfiles->{data});
  779.     for (my $i = 0; $i < @lines; $i++) {
  780.     my $line = trim(remComment($lines[$i]));
  781.     $line =~ /(.+)=.+,+(.*)/;
  782.     my $file = trim($1);
  783.     my $dir = trim($2);
  784.     if ($file and $dir and lc($filename) eq lc($file)) {
  785.         return $dir;
  786.     }
  787.     }
  788.     return "";
  789. }
  790.  
  791. #
  792. # Find a file in a case-insensitive way.
  793. #
  794. sub findfile {
  795.     my $dir = shift;
  796.     my $file = shift;
  797.  
  798.     if (!opendir(DIR, "$instdir/$dir")) {
  799.     print "Unable to open $instdir\n";
  800.     return "";
  801.     }
  802.     my @allfiles = readdir(DIR);
  803.     for (my $i = 0; $i < @allfiles; $i++) {
  804.     if (lc($allfiles[$i]) eq lc($file)) {
  805.         closedir(DIR);    
  806.         return $allfiles[$i]; 
  807.     }
  808.     }
  809.     closedir(DIR);    
  810.     return "";
  811. }
  812.  
  813. #
  814. # This section contains pointers to the section with the parameters to be
  815. # added to the registry.
  816. #
  817. sub addReg {
  818.     my $reg_name = shift;
  819.     my $reg = getSection($reg_name);
  820.     if (!$reg) {
  821.     printf "Parse error in inf. Unable to find section $reg_name\n";
  822.     return -1;
  823.     }
  824.  
  825.     my $param;
  826.     my $type;
  827.     my $val;
  828.     my $found;
  829.     my $gotParam = 0;
  830.     my @lines = split("\n", $reg->{data});
  831.     for (my $i = 0; $i < @lines; $i++) {
  832.     my $line = trim(remComment($lines[$i]));
  833.     if ($line) {
  834.         $line =~ /([^,]*),([^,]*),([^,]*),([^,]*),(.*)/; 
  835.         my $hkr = trim($1);
  836.         my $p1 = stripquotes(substStr(trim($2)));
  837.         my $p2 = stripquotes(substStr(trim($3)));
  838.         my $p3 = stripquotes(substStr(trim($4)));
  839.         my $p4 = stripquotes(substStr(trim($5)));
  840.  
  841.         if ($p1) {
  842.         if($p1 =~ /ndi\\params\\(.+)/i) {
  843.             $1 =~ /(.+)\\.*/;
  844.             if ($1 ne $param) {
  845.             $found = 0;
  846.             $param = $1;
  847.             $type = "";
  848.             $val = "";
  849.             }
  850.             if (lc($p2) eq "type") {
  851.             $found++;
  852.             $type = $p4;
  853.             } elsif (lc($p2) eq "default") {
  854.             $found++;
  855.             $val = $p4;
  856.             }
  857.  
  858.             if ($found == 2) {
  859.             $gotParam = 1;
  860.             }
  861.         }
  862.         } else {
  863.         $param = $p2;
  864.         $val = $p4;
  865.         $gotParam = 1;
  866.         }
  867.  
  868.         if ($gotParam and $param ne "" and $param ne "BusType") {
  869.         my $s = "$param|$val";
  870.         if ($param_fixlist{"$s"}) {
  871.             my $sOld = $s;
  872.             $s = $param_fixlist{"$s"};
  873.             print "Forcing parameter $sOld to $s\n"; 
  874.         }
  875.         print CONF "$s\n";
  876.         $param = "";
  877.         $gotParam = 0;
  878.         }
  879.     }
  880.     }
  881. }
  882.  
  883. sub substStr {
  884.     my $s = shift;
  885.     if ($s =~ /^\%(.+)$\%/) {
  886.     return getString($1);
  887.     }
  888.     return $s;
  889. }
  890.  
  891. #
  892. # Parse a device-id line.
  893. #
  894. sub parseID {
  895.     my $s = uc(shift);
  896.     if ($s =~ /PCI\\VEN_(\w+)&DEV_(\w+)&SUBSYS_(\w{4})(\S{4})/) {
  897.     return ($WRAP_PCI_BUS, $1, $2, $4, $3);
  898.     } elsif ($s =~ /PCI\\VEN_(\w+)&DEV_(\w+)/) {
  899.     return ($WRAP_PCI_BUS, $1, $2);
  900.     } elsif ($s =~ /USB\\VID_(\w+)&PID_(\w+)/) {
  901.     return ($WRAP_USB_BUS, $1, $2);
  902.     }
  903. }
  904.  
  905. #
  906. # remove whitsepace at front and end.
  907. #
  908. sub trim {
  909.     my $s = shift;
  910.     $s =~ s/^\s*//;
  911.     $s =~ s/\s*$//;
  912.     return $s;
  913. }
  914.  
  915. sub stripquotes {
  916.     my $s = shift;
  917.     $s =~ s/"(.*)"/$1/;
  918.     return $s;
  919. }
  920.  
  921. sub getKeyVal {
  922.     my $line = shift;
  923.  
  924.     $line = remComment($line);
  925.     (my $key, my $val) = split("=", $line);
  926.     if ($line =~ /(.+)=(.+)/) {
  927.     return (trim($1), trim($2));
  928.     }
  929. }
  930.  
  931. sub remComment {
  932.     my $s = shift;
  933.     $s=~ s/([^;]*);.*/$1/;
  934.     return $s;
  935. }
  936.  
  937. #
  938. # Initialize the string symbol table
  939. #
  940. sub initStrings {
  941.     my $s = getSection("strings");
  942.     if (!$s) {
  943.     return;
  944.     }
  945.     my @lines = split("\n", $s->{data});
  946.  
  947.     for (my $i = 0; $i < @lines; $i++) {
  948.     (my $key, my $val) = getKeyVal($lines[$i]);
  949.     if ($key) {
  950.         $val =~ s/"(.+)"/$1/; 
  951.         $strings{$key} = $val;
  952.     }
  953.     }
  954. }
  955.  
  956. #
  957. # fetch a string from the symbol table
  958. #
  959. sub getString {
  960.     my $s = shift;
  961.     return $strings{$s};
  962. }
  963.  
  964. #
  965. # Loacate a section.
  966. #
  967. sub getSection {
  968.     my $needle = shift;
  969.  
  970.     for (my $i = 0; $i < @sections;  $i++) {
  971.     if ( lc($sections[$i]->{name}) eq lc($needle)) {
  972.         return $sections[$i];
  973.     }
  974.     }
  975.     return 0;
  976. }
  977.  
  978. #
  979. # Load inf and split into different sections.
  980. #
  981. sub loadinf {
  982.     my $filename = shift;
  983.     my %def_section;
  984.     my $section = \%def_section;
  985.  
  986.     if (!open(INF, $filename)) {
  987.     return -1;
  988.     }
  989.  
  990.     my $i = 0;
  991.     $section->{name} = "none";
  992.     while (my $s = <INF>) {
  993.     #Convert from unicode
  994.     $s =~ s/\xff\xfe//;
  995.     $s =~ s/\0//g;
  996.  
  997.     $s =~ s/\s*$//;    #Remove trailing whitespace and \r
  998.     $s .= "\n";
  999.     if ($s =~ /^\[(.+)\]/) {
  1000.         $sections[$i++] = $section;        
  1001.         my %new_section;
  1002.         $section = \%new_section;
  1003.         $section->{name} = $1;
  1004.     } else {
  1005.         $section->{data} .= $s;
  1006.     }
  1007.     }
  1008.     $sections[$i++] = $section;  
  1009.     close(INF);
  1010. }
  1011.  
  1012. ## Local Variables: ##
  1013. ## cperl-indent-level: 4 ##
  1014. ## End: ##
  1015.